package clause

import (
	"strings"
)

// Clause contains SQL conditions
type Clause struct {
	sql     map[Type][]string
	sqlVars map[Type][]interface{}
}

// Type is the type of Clause
type Type int

// Support types for Clause
const (
	INSERT Type = iota
	VALUES
	SELECT
	LIMIT
	OFFSET
	WHERE
	OR
	GROUPBY
	ORDERBY
	HAVING
	UPDATE
	DELETE
	COUNT
	JOIN
)

// Set adds a sub clause of specific type
func (c *Clause) Set(name Type, vars ...interface{}) {
	if c.sql == nil {
		c.sql = make(map[Type][]string)
		c.sqlVars = make(map[Type][]interface{})
	}
	sql, vars := generators[name](vars...)

	if name == WHERE && len(c.sql[name]) != 0 {
		sql = strings.Replace(sql, "WHERE", "AND", -1)
	}

	if name == VALUES && len(c.sql[name]) != 0 {
		sql = strings.Replace(sql, "VALUES", ",", -1)
	}
	if name == INSERT && len(c.sql[name]) != 0 {
		return
	}

	if name == SELECT && len(c.sql[name]) != 0 {
		// 清空 select
		c.sql[name] = []string{}
	}

	if name == COUNT && len(c.sql[name]) != 0 {
		c.sql[name] = []string{}
	}

	if name == UPDATE && len(c.sql[name]) != 0 {
		c.sql[name] = []string{}
		c.sqlVars[name] = []interface{}{}
	}

	c.sql[name] = append(c.sql[name], sql)
	c.sqlVars[name] = append(c.sqlVars[name], vars...)
}

// 提供一个Get方法，用于获取Clause中的sql和sqlVars
// Get returns the sql and sqlVars of specific type
func (c *Clause) Get(name Type) (string, []interface{}) {
	//  c.sql[name] 转成string
	// c.sqlVars[name] 转成[]interface{}
	return strings.Join(c.sql[name], " "), c.sqlVars[name]
}

// Build generate the final SQL and SQLVars
func (c *Clause) Build(orders ...Type) (string, []interface{}) {
	var sqls []string
	var vars []interface{}
	for _, order := range orders {
		if sql, ok := c.sql[order]; ok {
			sqls = append(sqls, sql...)
			vars = append(vars, c.sqlVars[order]...)
		}
	}
	return strings.Join(sqls, " "), vars
}
